import allure
import pytest
from _pytest.fixtures import FixtureRequest
from playwright.sync_api import sync_playwright
from pytest import Item

from constant.constants import PlaywrightConfig
from public.project_patch import COOKIES, DOWNLOAD_DIR, TRACE_DIR

test_info = {}


@pytest.fixture(scope="session")
def start_playwright():
    p = sync_playwright().start()
    yield p
    p.stop()


@pytest.fixture(scope="session")
def context(start_playwright):
    """
    浏览器fixture
    :param start_playwright:
    :return: 禁用窗口大小
    """
    browser = start_playwright.chromium.launch(
        headless=False,
        slow_mo=PlaywrightConfig.SLOW_MO,
        args=["--start-maximized", f"--download.default_directory={DOWNLOAD_DIR}"],
    )
    context = browser.new_context(no_viewport=True)
    context.grant_permissions(["camera", "microphone"])
    context.set_default_navigation_timeout(
        PlaywrightConfig.DEFAULT_NAVIGATION_TIMEOUT
    )  # 设置全局超时时间40s
    yield context
    context.close()
    browser.close()


@pytest.fixture(scope="session")
def browser_context_args(browser_context_args, pytestconfig, playwright):
    """page启动参数"""
    iphone_11 = playwright.devices["iPhone 11 Pro"]
    return {
        **browser_context_args,
        "ignore_https_errors": True,  # 忽略https 错误
        "viewport": {"width": 1920, "height": 1080},  # 自定义浏览器窗口大小
        "storage_state": pytestconfig.rootpath.joinpath(COOKIES),  # cookie
        **iphone_11,
        "locale": "zh-CN",
    }


@pytest.fixture(scope="function", autouse=True)
def module_name_function(request):
    """测试模块名称"""
    return request.module.__name__


@pytest.fixture(scope="function", autouse=True)
def func_name_function(request):
    """测试函数名称"""
    return request.function.__name__


@pytest.fixture(scope="session")
def page(context):
    """浏览器page"""
    page = context.new_page()
    page.set_default_timeout(PlaywrightConfig.DEFAULT_OPERATIONAL_ELEMENT_TIMEOUT)
    yield page
    page.close()


@pytest.fixture(scope="function", autouse=True)
def trace_viewer(context, browser_name, module_name_function, func_name_function):
    """trace viewer追踪"""
    context = context
    context.tracing.start(screenshots=True, snapshots=True)
    yield
    module_name = module_name_function.split(".")[-1]
    trace_viewer_file = (
        TRACE_DIR
        / f"{module_name}"
        / f"{func_name_function}"
        / f"{browser_name}"
        / "trace.zip"
    )
    context.tracing.stop(path=trace_viewer_file)


def pytest_runtest_call(item: Item):
    """动态添加测试类的feature、测试用例的title"""
    if item.parent._obj.__doc__:
        allure.dynamic.feature(item.parent._obj.__doc__)
    if item.function.__doc__:
        allure.dynamic.title(item.function.__doc__)


def pytest_collection_modifyitems(items):
    """兼容中文显示"""
    for item in items:
        item.name = item.name.encode("utf-8").decode("unicode_escape")
        item._nodeid = item.nodeid.encode("utf-8").decode("unicode_escape")


@pytest.fixture(autouse=True)
def set_test_info(request: FixtureRequest):
    """获取当前用例所属类、目录、方法名、用例名称等相关信息,并存入全局变量以供使用"""
    global test_info
    node_id = request.node.nodeid
    test_info["case_name"] = request.node.name
    test_info["method_name"] = request.node.name.split("[")[0]
    test_info["class_name"] = node_id.split("::")[1]
    test_info["directory"] = node_id.split("/")[2]
